
import { Sprite, Node } from "cc";
import { Component } from "cc";
// import AssetsLoader from "../AssetsLoader";
import GameInputEvent from "./GameInputEvent";
import { CtrlModeListener, SingleKeyListener } from "./GameInputListeners";
import GameInputMgr from "./GameInputMgr";
import { ConfigInfo } from "./InputConfig";
import InputConverter from "./InputConverter";


class InputObserver {
    name: string//类名
    target: any
    infos: ConfigInfo[] = []//配置表id

    emit(keyCode: number, data: any) {
        let list: ConfigInfo[] = this.infos
        if (!list || !this.target) {
            console.log('InputObserver list  or target is null')
            return;
        }
        // console.log('InputObserver list.length', list.length)
        for (let index = 0; index < list.length; index++) {
            const element = list[index];
            let keyValue = GameInputMgr.getInstance().converter.getKeyValueByKeyName(element.keycode)
            if (keyValue == keyCode) {
                let func = this.target[element.function]
                if (func) {
                    func.call(this.target, data)
                }
                break;
            }
        }
        // console.log('InputObserver list.length22222222222222', list.length)
    }
}

class InputGroup {
    group: number;
    observer: InputObserver[] = []

    add(obj: InputObserver) {
        this.observer.push(obj)
    }

    remove(name: string) {
        for (let index = 0; index < this.observer.length; index++) {
            const element = this.observer[index];
            if (element.name == name) {
                this.observer.splice(index, 1)
                break;
            }
        }
    }

    emit(keyCode: number, data: any) {
        console.log(' this.observer.length', this.observer.length)
        for (let index = 0; index < this.observer.length; index++) {
            const element = this.observer[index];
            element.emit(keyCode, data)
        }
    }

    isEmpty() {
        return this.observer.length == 0
    }
}


export default class GameInputOperator implements SingleKeyListener, CtrlModeListener {



    private static ins: GameInputOperator
    static getInstance() {
        if (!this.ins) {
            this.ins = new GameInputOperator();
        }
        return this.ins;
    }

    private groupList: InputGroup[] = []
    //每个界面对应的多行数据
    private nameInfo: { [key: string]: ConfigInfo[] } = {}
    //界面名称与组id的映射
    protected nameGroup: { [key: string]: number } = {}

    //提示图片的配置信息。
    protected keyCfg: { [key: string]: { cc_key: string, steam_key: string } } = {};

    init(config: any, keyConfig: any) {
        for (const key in keyConfig) {
            const element = keyConfig[key];
            this.keyCfg[element.self] = element;
        }
        // this.keyCfg = ;
        for (const key in config) {
            const element = config[key];
            this.nameGroup[element.name] = element.group;
            let name = element.name
            let data = this.nameInfo[name]
            if (!data) {
                data = []
                this.nameInfo[name] = data;
            }
            data.push(element)
        }
        this.start();

    }

    private getGroup(group: number) {
        for (let index = 0; index < this.groupList.length; index++) {
            const element = this.groupList[index];
            if (element.group == group) {
                return index;
            }
        }
        return -1;
    }

    on(name: string, target: any) {
        let info: ConfigInfo[] = this.nameInfo[name]
        let group = this.nameGroup[name]
        if (!group) {
            return;
        }
        let index = this.getGroup(group)
        let data = null;
        if (index < 0) {
            data = new InputGroup();
            data.group = group;
            this.groupList.push(data)
        } else {
            data = this.groupList[index]
        }
        let observer = new InputObserver()
        observer.name = name;
        observer.target = target;
        observer.infos = info;
        data.add(observer)
        this.addTipPic(name, target)
    }

    off(name: string) {
        let group = this.nameGroup[name]
        if (!group) {
            return;
        }
        let index = this.getGroup(group)
        if (index >= 0) {
            let data = this.groupList[index]
            data.remove(name)
            if (data.isEmpty()) {
                this.groupList.splice(index, 1)
            }
        }
    }

    /**
     * 根据名称获得子节点
     * @param name 节点名称
     * @param root 父节点
     * @returns 
     */
    private find(name: string, root: Node) {
        let children = root.children;
        let result = null;
        for (let index = 0; index < children.length; index++) {
            const element = children[index];
            if (element.name == name) {
                result = element;
                break;
            } else {
                result = this.find(name, element)
                if (result) {
                    break;
                }
            }
        }
        return result;
    }

    /**
     * 给界面上的按钮动态的添加提示图片
     * @param name 
     * @param target 
     */
    addTipPic(name: string, target: any) {
        let t: Component = null;
        if (name.indexOf('Mediator') >= 0) {
            t = target.viewComponent;
        } else {
            t = target;
        }
        let info: ConfigInfo[] = this.nameInfo[name]
        for (let index = 0; index < info.length; index++) {
            const element = info[index];
            if (!element.button) {
                continue;
            }
            let button = this.find(element.button, t.node)
            if (button) {
                let temp = this.find('tip', button)
                if (!temp) {
                    continue;
                }
                let sp: Sprite = temp.getComponent(Sprite);
                if (!sp) {
                    continue;
                }

                let data = this.keyCfg[element.keycode]
                if (data) {
                    let platName = GameInputMgr.getInstance().getCfgName()
                    // console.log(' GameInputOperator data ', data)
                    // console.log(' GameInputOperator platName ', platName)
                    let path = 'key/' + data[platName]
                    console.log(' GameInputOperator path ', path)
                    // console.log(' sp ', sp)
                    if (path) {
                        // AssetsLoader.loadSpriteFrame(path, sp)
                        // AssetsLoader.loadAssetSync(path, SpriteFrame)
                        //     .then((res: SpriteFrame) => {
                        //         if (sp && sp.node.isValid) {
                        //             sp.spriteFrame = res;
                        //         } else {
                        //             console.log(' GameInputOperator no ok path ', path)
                        //         }

                        //     }).catch(() => {
                        //         console.log(' GameInputOperator error path ', path)
                        //     })

                    } else {
                        if (sp.node.active)
                            sp.node.active = false;
                    }

                }
            }
        }
    }

    onChangeMode(mode: string): void {
        let list = this.groupList;
        for (let index = 0; index < list.length; index++) {
            const group = list[index];
            let ls = group.observer;
            for (let j = 0; j < ls.length; j++) {
                const observer = ls[j];
                this.addTipPic(observer.name, observer.target)
            }
        }
    }

    isBlockInput(): boolean {
        return false;
    }

    onKeyBoardPress(keyCode: number, data: GameInputEvent): void {
        console.log("GameInputOperator onKeyBoardRelease " + data.keyCode, keyCode);
    }

    onKeyBoardRelease(keyCode: number, data: GameInputEvent): void {
        // console.log("GameInputOperator onKeyRelease:1111 " + keyCode, this.groupList.length);
        if (this.groupList.length > 0) {
            let observer: InputGroup = this.groupList[this.groupList.length - 1]
            if (observer) {
                observer.emit(keyCode, data)
            }
        }
        console.log("GameInputOperator onKeyBoardRelease " + data.keyCode, keyCode);
    }

    start() {
        GameInputMgr.getInstance().addKeyListener(this)
        GameInputMgr.getInstance().addCtrlModeListener(this)
    }

    update(deltaTime: number) {
        let event: GameInputEvent = GameInputMgr.getInstance().getKeyEvent();
        if (event.keyCode > 0) {
            // console.log(' event keycode ', event.keyCode)
        }
    }

    onDestroy() {
        GameInputMgr.getInstance().removeKeyListener(this)
        GameInputMgr.getInstance().removeCtrlModeListener(this)
    }
}

